package com.usian.admin.gateway.filter;/*
 *文件名：AuthorizeFilter
 *创建者：宋璟
 *创建时间:2023/2/6 18:31
 *描述: TODO
 */

import com.usian.jwt.utils.AppJwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.function.Consumer;

@Component
@Log4j2
public class AuthorizeFilter implements GlobalFilter , Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求对象和响应对象
        //客户端已经将要请求的路径，参数等一系列东西包括请求否，给到他了，他已经拿着东西出发了
        ServerHttpRequest request = exchange.getRequest();
        //现在用不上 当我们的网管具体路由到某个服务，这个服务且查表成功，将数据塞到response里面
        ServerHttpResponse response = exchange.getResponse();

        //先登录在放行  判断当前是否登录  request参数都在里面，拿到请求路径url，进行解码path
        if(request.getURI().getPath().contains("/login/in")){ //当前是登录接口的访问，不做校验
            //放行
            return chain.filter(exchange);
        }

        //从请求对象里面拿到了请求头
        HttpHeaders headers = request.getHeaders();
        // first 第一个token,只有一个token，就怕获取多了所以用了first 从请求头里获取token
        String token = headers.getFirst("token");

        if (StringUtils.isBlank(token)){
            //提示没有token
            String json = "{\"errorMsg\":\"dont have token\"}";
            //放到response 告诉前段没有传输的 bufferFactory工厂化的重新构建
            //wrap 在构建的时候包裹了一个bytes数组 just可以在里面存放多个元素
            //response  在response里（writeWith）写入个Flux.just(response.bufferFactory().wrap(json.getBytes()))
            return response.writeWith(Flux.just(response.bufferFactory().wrap(json.getBytes())));
        }

        //4.判断当前令牌是否存在
        /*if(StringUtils.isEmpty(token)){
            //如果不存在，向客户端返回错误提示信息
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }*/


        //token是请求头里的
        //getClaimsBody(token)已经做了效验了  效验的是合法性问题
        Claims claims = AppJwtUtil.getClaimsBody(token);
        //效验的是时效性  verifyToken里面是过期时间
        int i = AppJwtUtil.verifyToken(claims);

        if (i == -1 || i == 0){
            Integer id = (Integer) claims.get("id");
            //重构头  接口回调  他是一个函数式接口
            ServerHttpRequest newRequest = request.mutate().headers(httpHeaders -> httpHeaders.add("userId", id+"")).build();
            exchange.mutate().request(newRequest).build();
        }
        //交换机丢过去，放行
        return chain.filter(exchange);
    }

    @Override
    //return 0 是优先级最高
    public int getOrder() {
        return 0;
    }















}
